
// 在 Objet.prototype 上声明的函数将来会被所有实例所继承

function Animal( type ){
    this.type = type ;
}
// 声明 Animal对象 时已经隐式完成了:
// Animal.prototype = new Object();
// Animal.prototype.constructor = Animal ;

function Beast( name , gender ){
    this.name = name ;
    this.gender = gender ;
}

Beast.prototype = new Animal( '兽' );
Beast.prototype.constructor = Beast ;

let b = new Beast( '牛魔王' , '男' );
console.log( b.toString() ); // Objet.prototype.toString()
console.log( b.toLocaleString() ); // Objet.prototype.toLocaleString()

// proto.isPrototypeOf( ref ) 用于测试 proto 是否存在于 ref 的原型链上
let ipo = Animal.prototype.isPrototypeOf( b );
// b.__proto__ 获取到的是 Beast.prototype 即一个 Animal实例
// b.__proto__.__proto__ 获取到的是 Animal.prototype
// b.__proto__.__proto__.__proto__ 获取到的是 Object.prototype
console.log( ipo );

console.log( Beast.prototype.isPrototypeOf( b ) );
console.log( Object.prototype.isPrototypeOf( b ) );

console.log( '- - - - - - - - - - - - - - -');

let p = new Object();
// 将p变量所引用的实例当作原型使用，来创建一个新的实例
let x = Object.create( p ) ;
console.log( p.isPrototypeOf( x ) );

console.log( '- - - - - - - - - - - - - - -');

let bird = { 
    type: '禽'
}

let pigeon = {
    name: '信鸽' 
}

Object.setPrototypeOf( pigeon , bird );

console.log( pigeon.type , pigeon.name );
console.log( bird.isPrototypeOf( pigeon ) ); // true
console.log( Object.prototype.isPrototypeOf( pigeon ) ); // true

console.log( Object.getPrototypeOf( pigeon ) === bird ); // true
console.log( pigeon.__proto__ === bird );//true

console.log( '- - - - - - - - - - - - - - -');

console.log( pigeon.hasOwnProperty( 'type' ) ); // false
console.log( pigeon.hasOwnProperty( 'name' ) ); // true

console.log( pigeon.propertyIsEnumerable( 'name' ) ); // true
// 此方法可以确定对象中指定的属性是否可以被 for...in 循环枚举，但是通过原型链继承的属性除外
console.log( pigeon.propertyIsEnumerable( 'type' ) ); // false

// 【问题】
// 如果将 bird 的 type 修改了，通过 pigeon.type 获取的值是否被修改?
// 为什么?